/*
 * 在 ASP.NET Core 中有多种缓存数据的方式，Orchard Core 也使用这些方式。例如，内容项使用 IMemoryCache 服务进行缓存。
 * 内存缓存将数据副本保存在本地服务器的内存中，这在大多数情况下可能就足够了。
 * 但是，某些功能需要一些额外的功能和更复杂的缓存方式，例如形状。
 * 在 Orchard Core 中有一个所谓的动态缓存，它建立在分布式缓存之上。
 * 分布式缓存在集中位置维护缓存，集群中的服务器可以访问该位置。
 * 在 Orchard Core 中，这也是内存缓存，但为使用 Redis 等打开了可能性。
 * 在本教程中，我们将看到缓存 DateTime 对象的几个示例，还将演示形状缓存。
 */

using Ruitu.Edu.TrainingDemo.Services;
using Ruitu.Edu.TrainingDemo.ViewModels;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

namespace Ruitu.Edu.TrainingDemo.Controllers;

/// <summary>
/// 缓存控制器 - 演示不同类型的缓存机制
/// 
/// 主要用途：
/// - 演示内存缓存的使用
/// - 展示动态缓存的功能
/// - 演示基于路由的缓存变化
/// - 展示形状缓存机制
/// 
/// 使用场景：
/// - 缓存频繁访问的数据
/// - 提高应用程序性能
/// - 减少数据库查询
/// - 实现分布式缓存
/// 
/// 设计原因：
/// - 展示 Orchard Core 的多种缓存策略
/// - 演示缓存失效机制
/// - 展示路由相关的缓存变化
/// 
/// 设计模式：
/// - 依赖注入模式：通过构造函数注入缓存服务
/// - 服务模式：将缓存逻辑封装在服务中
/// - 视图模型模式：使用 ViewModel 传递数据到视图
/// </summary>
public sealed class CacheController : Controller
{
    // 实际的缓存实现在一个服务中，我们很快就会研究它。
    private readonly IDateTimeCachingService _dateTimeCachingService;

    /// <summary>
    /// 构造函数 - 通过依赖注入初始化缓存服务
    /// </summary>
    /// <param name="dateTimeCachingService">日期时间缓存服务，用于演示不同类型的缓存</param>
    public CacheController(IDateTimeCachingService dateTimeCachingService) => _dateTimeCachingService = dateTimeCachingService;

    /// <summary>
    /// 缓存演示主页 - 展示三种不同的缓存方式
    /// 
    /// 在此操作中，我们将以三种不同的方式缓存 DateTime。
    /// 您可以通过 /Ruitu.Edu.TrainingDemo/Cache/Index 访问它
    /// </summary>
    /// <returns>返回包含缓存数据的视图</returns>
    public async Task<ActionResult> Index()
    {
        // 这个将使用内置的 ASP.NET Core IMemoryCache 进行缓存。
        var memoryCachedDateTime = await _dateTimeCachingService.GetMemoryCachedDateTimeAsync();

        // 这个将使用 Orchard Core 提供的 DynamicCache。它将有 30 秒的过期时间。
        var dynamicCachedDateTimeWith30SecondsExpiry =
            await _dateTimeCachingService.GetDynamicCachedDateTimeWith30SecondsExpiryAsync();

        // 最后，这个日期将仅为此路由缓存。
        var dynamicCachedDateTimeVariedByRoutes =
            await _dateTimeCachingService.GetDynamicCachedDateTimeVariedByRoutesAsync();

        // 下一站：Services/DateTimeCachingService.cs

        return View("Index", new CacheViewModel
        {
            MemoryCachedDateTime = memoryCachedDateTime,
            DynamicCachedDateTimeWith30SecondsExpiry = dynamicCachedDateTimeWith30SecondsExpiry,
            DynamicCachedDateTimeVariedByRoutes = dynamicCachedDateTimeVariedByRoutes,
        });
    }

    /// <summary>
    /// 不同路由演示 - 测试基于路由的缓存变化
    /// 
    /// 此操作将产生与 Index 相同的页面，但是路由将不同，
    /// 因此可以测试特定于路由的缓存。您可以通过 /Ruitu.Edu.TrainingDemo/Cache/DifferentRoute 访问它
    /// </summary>
    /// <returns>返回与 Index 相同的视图</returns>
    public Task<ActionResult> DifferentRoute() =>
        Index();

    /// <summary>
    /// 使缓存失效 - 演示缓存失效机制
    /// 
    /// 此操作将使内存缓存和所有特定于路由的缓存失效。
    /// 调用此操作将重定向回 Index 页面，您会注意到日期值已更新。
    /// 您可以通过 /Ruitu.Edu.TrainingDemo/Cache/InvalidateDateTimeCache 访问它
    /// </summary>
    /// <returns>重定向到 Index 页面</returns>
    public async Task<ActionResult> InvalidateDateTimeCache()
    {
        await _dateTimeCachingService.InvalidateCachedDateTimeAsync();

        return RedirectToAction("Index");
    }

    /// <summary>
    /// 形状缓存演示 - 展示 Orchard Core 如何最充分地利用动态缓存
    /// 
    /// 在此操作中，您将看到形状是如何被缓存的。
    /// 您可以通过 /Ruitu.Edu.TrainingDemo/Cache/Shape 访问它
    /// </summary>
    /// <returns>返回形状缓存演示视图</returns>
    public ActionResult Shape() =>
        View();

    // 下一站：Views/Cache/Shape.cshtml
}
